package org.vectrics.graphics;

import java.awt.Color;
import java.awt.Container;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Shape;
import java.awt.Toolkit;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Rectangle2D;
import java.awt.geom.RoundRectangle2D;
import java.awt.image.BufferedImage;
import java.awt.image.ImageObserver;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Iterator;

import org.apache.log4j.Logger;
import org.vectrics.SystemException;
import org.vectrics.common.html.ColorUtil;

public class DynaGraphicRenderer implements ImageObserver {
	private DynaGraphic dynaGraphic = null;
	private Logger log = Logger.getLogger(DynaGraphicRenderer.class);
	
	public boolean imageUpdate(Image image, int a, int b, int c, int d, int e) {
		log.info("imageUpdate() image=" + image 
				+ " a=" + a 
				+ " b=" + b 
				+ " c=" + c 
				+ " d=" + d 
				+ " e=" + e 
				);
		return(true);
	}
	
	public DynaGraphicRenderer(DynaGraphic dynaGraphic) {
		this.dynaGraphic = dynaGraphic;
	}
	
	/* 
     * @see org.vectrics.common.graphics.Graphic#doFill(java.awt.Graphics2D)
     */
    protected void doFill(Graphics2D graphics2d) {
        Iterator iter = dynaGraphic.getConfiguration().getPathLayerList().iterator();
        //String backgroundColor = configuration.getPathBackground();
        
        while (iter.hasNext()) {
            LayerConfiguration layer = (LayerConfiguration)iter.next();
    		if (layer.getAntiAliasing()) {
    			RenderingHints aliasingConfig = new	RenderingHints(RenderingHints.KEY_ANTIALIASING, 
    			        RenderingHints.VALUE_ANTIALIAS_ON);
    			graphics2d.addRenderingHints(aliasingConfig);
    		} else {
    			RenderingHints aliasingConfig = new	RenderingHints(RenderingHints.KEY_ANTIALIASING, 
    			        RenderingHints.VALUE_ANTIALIAS_OFF);
    			graphics2d.addRenderingHints(aliasingConfig);
    		}
            
            if (layer instanceof LayerTextConfiguration) {
                LayerTextConfiguration textLayer = (LayerTextConfiguration)layer;
                renderTextLayer(graphics2d, textLayer);
            } else if (layer instanceof LayerImageConfiguration) {
                LayerImageConfiguration imageLayer = (LayerImageConfiguration)layer;
                renderFileImage(graphics2d, imageLayer);
            } else if (layer instanceof LayerShapeConfiguration) {
                LayerShapeConfiguration shapeLayer = (LayerShapeConfiguration)layer;
                renderShapeLayer(graphics2d, shapeLayer);
            } else {
                throw new SystemException("Do not know how to handle layer type: " 
                		+ layer.getClass().getName() + "  Image name = " + this.dynaGraphic.getConfiguration().getName());
            }
        }
    }
    
    
    private void renderShapeLayer(Graphics2D graphics2d, LayerShapeConfiguration layer) {
        int width = this.dynaGraphic.getWidth() - 1;
        int height = this.dynaGraphic.getHeight() - 1;
        int left = 0;
        int top = 0;
        
        if (layer.getWidth() != null)
            width = layer.getWidth().intValue();
        if (layer.getHeight() != null)
            height = layer.getHeight().intValue();
        
        left = layer.getLeft();
        top = layer.getTop();
        
        
        double x = left;
        double y = top;
        double w = width;
        double h = height;
        double arcw = 0;
        double arch = 0;
        if (layer.getRadius() != null) {
	        arcw = layer.getRadius().doubleValue();
	        arch = layer.getRadius().doubleValue();
        }

        Color brushColor = null;
        Color penColor = null;
        if (layer.getBrushColor() != null)
            brushColor = ColorUtil.htmlStringToColor(layer.getBrushColor());
        if (layer.getPenColor() != null)
            penColor = ColorUtil.htmlStringToColor(layer.getPenColor());

        Shape shape = new  RoundRectangle2D.Double(x, y, w, h, arcw, arch);
        if (layer.getShapeType() == LayerShapeConfiguration.SHAPE_TYPE_ROUND_RECTANGLE) {
            shape = new  RoundRectangle2D.Double(x, y, w, h, arcw, arch);
        } else if (layer.getShapeType() == LayerShapeConfiguration.SHAPE_TYPE_RECTANGLE) {
            shape = new  Rectangle2D.Double(x, y, w, h);
        } else if (layer.getShapeType() == LayerShapeConfiguration.SHAPE_TYPE_ELLIPSE) {
            shape = new  Ellipse2D.Double(x, y, w, h); 
        }

        if (brushColor != null) {
            graphics2d.setColor(brushColor);
            graphics2d.setPaint(brushColor);
            graphics2d.fill(shape);
        }
        if (penColor != null) {
            graphics2d.setPaint(penColor);
            graphics2d.setColor(penColor);
            graphics2d.draw(shape);
        }
    }
    
    
    private void renderFileImage(Graphics2D graphics2d, LayerImageConfiguration layer) {
    	log.info("renderFileImage() - reading image from file and writing to layer");
        byte[] imageBytes = null;
        String fileName = layer.getPath();
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Image image = toolkit.getImage(fileName);
	    MediaTracker mediaTracker = new MediaTracker(new Container());
	    mediaTracker.addImage(image, 0);
	    try {
	    	mediaTracker.waitForID(0);
	    } catch (Exception ex) {
	    	throw new SystemException("Exception waiting for image", ex);
	    }
		
		try {
			log.info("Render image, image:" +
					"\r\n - width  = " + image.getWidth(this) +
					"\r\n - height = " + image.getHeight(this) +
					"\r\n - source = " + image.getSource()
					);
			
		    int left = layer.getLeft();
		    int top = layer.getTop();
		    int width = image.getWidth(this);
		    int height = image.getHeight(this);
		    graphics2d.drawImage(image, left, top, width, height, this);
		}
		catch (Exception ex) {
			log.error("Exception loading file: " + fileName, ex);	
		}
    }
    
/*
	private Image getImageFromBytes(byte[] imageBytes) {
		Toolkit toolkit = Toolkit.getDefaultToolkit();
		Image image = toolkit.createImage(imageBytes);
		toolkit.checkImage(image, )
		return(image);
	}
*/
    
    private void renderTextLayer(Graphics2D graphics2d, LayerTextConfiguration layer) {
		log.debug("Adding anti-aliasing");
				
		int fontWeight = Font.PLAIN;
		if (layer.getBold()) {
			fontWeight = Font.BOLD;
		}
		
	    Color textColor = ColorUtil.htmlStringToColor(layer.getColor());

	    if (textColor == null) {
	        textColor = Color.BLACK;
	    } 
		graphics2d.setColor(textColor);
		graphics2d.setBackground(textColor);
		graphics2d.setPaint(textColor);
		
		Font font = new Font("Arial", fontWeight, layer.getSize());
		graphics2d.setFont(font);
		int fontHeight = layer.getSize();
		if  ((layer.getValue() == null) && (layer.getValueCode() == null)) {
		    throw new SystemException("Text layer doesn't have text 'value' or 'valueCode' " +
		    		"property, layer name = " + layer.getName() + "  Image name = " 
		    		+ this.dynaGraphic.getConfiguration().getName());
		}
		String textValue = this.dynaGraphic.getTextLayerCaption(layer);
		
		graphics2d.drawString(textValue, layer.getLeft(), layer.getTop() 
				+ 5 + fontHeight - (fontHeight / 2));        
    }

}
